package com.yabushan.web.controller.data;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import com.yabushan.common.utils.DateUtils;
import com.yabushan.common.utils.StringUtils;
import com.yabushan.system.domain.*;
import com.yabushan.system.service.*;
import io.swagger.annotations.Api;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;


import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author yabushan
 * @memo 数据中台请求服务
 * @Date 2021/3/28 18:36
 * @Version 1.0
 */
@RestController
@Api(tags = "数据中台请求服务接口")
public class DataController {


    @Value("${daas.url}")
    private String url;
    @Value("${daas.accessKeyId}")
    private String accessKeyId;
    @Value("${daas.secertKey}")
    private String secertKey;
    @Value("${daas.projectId}")
    private String projectId;
    @Autowired
    private IDataApiInfosService dataApiInfosService;

    @Autowired
    private IMetadataDatasourceCustomerService metadataDatasourceService;
    @Autowired
    private IDataApiLogService dataApiLogService;

    @Autowired
    private IDataAliApiService aliApiService;

    @Autowired
    private IDataAliApiLogService aliApiLogService;

    @PostMapping(value = "/data/getMessageRow")
    public String getMessageRow(String ApiCode,String requestDev, String param) {

        String validate = validate(ApiCode, param,requestDev);
        if(validate!=null){
            return validate;
        }
        DataApiLog dataApiLog=new DataApiLog();
        dataApiLog.setApiCode(ApiCode);
        dataApiLog.setParamInfo(param);
        dataApiLog.setRequestUser(requestDev);

        String reslt = result(param, ApiCode,"row");
        JSONObject jsonObject = JSON.parseObject(reslt);
        String resultCode = jsonObject.getString("resultCode");
        String resultDesc = jsonObject.getString("resultDesc");
        String exception = jsonObject.getString("exception");
        String columnNames = jsonObject.getString("columnNames");
        String rows = jsonObject.getString("rows");
        ResultUtil resultUtil = new ResultUtil();
        resultUtil.setException(exception);
        resultUtil.setColumnNames(columnNames);
        resultUtil.setResultCode(resultCode);
        resultUtil.setRows(rows);
        dataApiLog.setResultCode(resultCode);
        dataApiLog.setResultInfo(toJson(resultUtil));
        dataApiLogService.insertDataApiLog(dataApiLog);
        return toJson(resultUtil);
    }

    @PostMapping(value = "/data/getMessageList")
    public String getMessageList(String ApiCode,String requestDev, String param) {

        String validate = validate(ApiCode, param,requestDev);
        if(validate!=null){
            return validate;
        }

        DataApiLog dataApiLog=new DataApiLog();
        dataApiLog.setApiCode(ApiCode);
        dataApiLog.setParamInfo(param);
        dataApiLog.setRequestUser(requestDev);


        String reslt = result(param, ApiCode,"list");
        JSONObject jsonObject = JSON.parseObject(reslt);
        String resultCode = jsonObject.getString("resultCode");
        String resultDesc = jsonObject.getString("resultDesc");
        String exception = jsonObject.getString("exception");
        String columnNames = jsonObject.getString("columnNames");
        String rows = jsonObject.getString("rows");
        ResultUtil resultUtil = new ResultUtil();
        resultUtil.setException(exception);
        resultUtil.setColumnNames(columnNames);
        resultUtil.setResultCode(resultCode);
        resultUtil.setRows(rows);
        dataApiLog.setResultCode(resultCode);
        dataApiLog.setResultInfo(toJson(resultUtil));
        dataApiLogService.insertDataApiLog(dataApiLog);
        return toJson(resultUtil);
    }


    public String result(String param, String apiCode,String rowType) {
        try {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String resourceApiCode = apiCode;//"test2_39"; //根据实际修改,也可以使用resourceId
            String urlPath = url + resourceApiCode;
            HttpPost httpPost = new HttpPost(urlPath);
            httpPost.setHeader("X-Amz-Date", format.format(new Date()));
            StringBuffer stringBuffer = new StringBuffer();
            if("row".equals(rowType)){
                stringBuffer.append("{'sqlMode':'normal','rowType':'row','dataServiceParams':");
            }else{
                stringBuffer.append("{'sqlMode':'normal','rowType':'list','dataServiceParams':");
            }

            stringBuffer.append(param);
            stringBuffer.append("}");
            String requestBody = stringBuffer.toString();
          
            String signature = "Bingoinsight" + ":" + accessKeyId + ":" + projectId + ":" + HmacSHA1Signer.getSignString(requestBody, secertKey);
            httpPost.setHeader("Authorization", signature);
            RequestConfig config = RequestConfig.custom().setSocketTimeout(220000).setConnectTimeout(220000).build(); // 握手超时、连接超时配置
            httpPost.setConfig(config);
            httpPost.setEntity(new StringEntity(requestBody, "UTF-8"));
            CloseableHttpClient client = HttpClients.createDefault();
            CloseableHttpResponse response = client.execute(httpPost);
            int statusCode = response.getStatusLine().getStatusCode();
            String resultJSON = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            return resultJSON;
        } catch (Exception e) {
            return e.toString();
        }

    }


    public String toJson(Object obj) {
        Gson gson = new GsonBuilder()
                .setDateFormat("yyyy-MM-dd HH:mm:ss").serializeNulls().disableHtmlEscaping().create();
        String strReturn = gson.toJson(obj);
        return strReturn;
    }

    public   String validate(String ApiCode,String param,String requestDev){
        String resultInfo = null;
        if(StringUtils.isEmpty(ApiCode)){
            return "服务编码不能为空!";
        }
        if(StringUtils.isEmpty(requestDev)){
            return "请求设备不能为空!";
        }
        if(StringUtils.isEmpty(param)){
            return "请求参数不能为空";
        }

        //判断API是否禁用
        DataApiInfos dataApiInfos = new DataApiInfos();
        dataApiInfos.setApiCode(ApiCode);
        dataApiInfos.setApiStatus("SUCCESS");
        List<DataApiInfos> dataApiInfos1 = dataApiInfosService.AppselectDataApiInfosList(dataApiInfos);
        if(dataApiInfos1.size()==0){
            return "API已被禁用，请联系管理员！";
        }else{
            //判断数据源是否审核通过
            MetadataDatasourceCustomer customer=new MetadataDatasourceCustomer();
            customer.setDatasourceId(dataApiInfos1.get(0).getDatasourceId());
            List<MetadataDatasourceCustomer> metadataDatasources = metadataDatasourceService.selectMetadataDatasourceCustomerList(customer);
            if(metadataDatasources.size()==0){
                return "数据库不存在，请联系管理员！";
            }
            if(!"SUCCESS".equals(metadataDatasources.get(0).getDatasourceStatus())){
                return "数据库已禁用或未被审核，请联系管理员！";
            }

        }



        return resultInfo;

    }

    @PostMapping(value = "/data/aliApi")
    public String aliApi(@RequestBody AliRequst aliRequst){
        //根据key获取信息
        DataAliApi dataAliApi = aliApiService.selectDataAliApiById(aliRequst.getKey());
        DataAliApiLog dataAliApiLog = new DataAliApiLog();
        dataAliApiLog.setCreatedTime(DateUtils.getNowDate());
        dataAliApiLog.setKeyId(aliRequst.getKey());
        dataAliApiLog.setReqparam(aliRequst.getQuerys());
        dataAliApiLog.setUserkey(aliRequst.getUserKey());

        String host = dataAliApi.getHostInfo();
        String path =dataAliApi.getPathInfo();
        String method = dataAliApi.getMethodInfo();
        String appcode = dataAliApi.getAppCode();
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        //根据API的要求，定义相对应的Content-Type
        if(StringUtils.isNotEmpty(dataAliApi.getContentType())){
            headers.put("Content-Type", dataAliApi.getContentType());
        }

        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> stringObjectMap = json2map(aliRequst.getQuerys());
        querys.putAll(stringObjectMap);
        try {
            /**
             * 重要提示如下:
             * HttpUtils请从
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
             * 下载
             *
             * 相应的依赖请参照
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
             */
            HttpResponse response = HttpUtils.doGet(host, path, method, headers, querys);
          String result =EntityUtils.toString(response.getEntity(),"utf-8");
            dataAliApiLog.setReqResult( result);
            dataAliApiLog.setEndTime(DateUtils.getNowDate());
            aliApiLogService.insertDataAliApiLog(dataAliApiLog);
            return result;
            //获取response的body
            //System.out.println(EntityUtils.toString(response.getEntity(),"utf-8"));
        } catch (Exception e) {
            dataAliApiLog.setReqResult("调用出错");
            aliApiLogService.insertDataAliApiLog(dataAliApiLog);
        }
        return null;

    }



    @PostMapping(value = "/data/juheApi")
     public String juheApi(@RequestBody AliRequst aliRequst){
         //根据key获取信息
         DataAliApi dataAliApi = aliApiService.selectDataAliApiById(aliRequst.getKey());
        DataAliApiLog dataAliApiLog = new DataAliApiLog();
        dataAliApiLog.setCreatedTime(DateUtils.getNowDate());
        dataAliApiLog.setKeyId(aliRequst.getKey());
        dataAliApiLog.setReqparam(aliRequst.getQuerys());
        dataAliApiLog.setUserkey(aliRequst.getUserKey());
        //发送http请求的url
        // String url = String.format(dataAliApi.getHostInfo(), dataAliApi.getKeyId(), aliRequst.getQuerys());
        Map paramMap =json2map(aliRequst.getQuerys());
        paramMap.put("key",dataAliApi.getAppCode());
        String queryParams = urlencode(paramMap);
        // 创建远程url连接对象
        String  url = new StringBuffer(dataAliApi.getHostInfo()).append("?").append(queryParams).toString();
         final String response = doGet(url);
        dataAliApiLog.setEndTime(DateUtils.getNowDate());
        aliApiLogService.insertDataAliApiLog(dataAliApiLog);
        return response;
     }


    public static void main(String[] args) {
        //接口请求地址
           String CAlENDAR_URL = "http://v.juhe.cn/laohuangli/d?key=%s&date=%s";
           String HOUR_URL = "http://v.juhe.cn/laohuangli/h?key=%s&date=%s";
        //申请接口的请求key
        // TODO: 您需要改为自己的请求key
          final String KEY = "您需要改为自己的请求key";
    }

    public static Map<String, String> json2map(String str_json) {
        Map<String, String> res = null;
        try {
            Gson gson = new Gson();
            res = gson.fromJson(str_json, new TypeToken<Map<String, String>>() {
            }.getType());
        } catch (JsonSyntaxException e) {
        }
        return res;
    }

    public static void main1(String[] args) {
        String host = "https://jisutqybmf.market.alicloudapi.com";
        String path = "/weather/query";
        String method = "GET";//GET/POST 任意
        String appcode = "518de9e18e2a4fd08288d74dc086b991";
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        //根据API的要求，定义相对应的Content-Type
        headers.put("Content-Type", "application/json; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        querys.put("city", "韶关");



        try {
            /**
             * 重要提示如下:
             * HttpUtils请从
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
             * 下载
             *
             * 相应的依赖请参照
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
             */
            HttpResponse response = HttpUtils.doGet(host, path, method, headers, querys);
            System.out.println(response.toString());
            //获取response的body
            System.out.println(EntityUtils.toString(response.getEntity(),"utf-8"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * get方式的http请求
     *
     * @param httpUrl 请求地址
     * @return 返回结果
     */
    public static String doGet(String httpUrl) {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        BufferedReader bufferedReader = null;
        String result = null;// 返回结果字符串
        try {
            // 创建远程url连接对象
            URL url = new URL(httpUrl);
            // 通过远程url连接对象打开一个连接，强转成httpURLConnection类
            connection = (HttpURLConnection) url.openConnection();
            // 设置连接方式：get
            connection.setRequestMethod("GET");
            // 设置连接主机服务器的超时时间：15000毫秒
            connection.setConnectTimeout(15000);
            // 设置读取远程返回的数据时间：60000毫秒
            connection.setReadTimeout(60000);
            // 发送请求
            connection.connect();
            // 通过connection连接，获取输入流
            if (connection.getResponseCode() == 200) {
                inputStream = connection.getInputStream();
                // 封装输入流，并指定字符集
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                // 存放数据
                StringBuilder sbf = new StringBuilder();
                String temp;
                while ((temp = bufferedReader.readLine()) != null) {
                    sbf.append(temp);
                    sbf.append(System.getProperty("line.separator"));
                }
                result = sbf.toString();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (null != bufferedReader) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();// 关闭远程连接
            }
        }
        return result;
    }


    /**
     * post方式的http请求
     *
     * @param httpUrl 请求地址
     * @param param   请求参数
     * @return 返回结果
     */
    public static String doPost(String httpUrl, String param) {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;
        BufferedReader bufferedReader = null;
        String result = null;
        try {
            URL url = new URL(httpUrl);
            // 通过远程url连接对象打开连接
            connection = (HttpURLConnection) url.openConnection();
            // 设置连接请求方式
            connection.setRequestMethod("POST");
            // 设置连接主机服务器超时时间：15000毫秒
            connection.setConnectTimeout(15000);
            // 设置读取主机服务器返回数据超时时间：60000毫秒
            connection.setReadTimeout(60000);
            // 默认值为：false，当向远程服务器传送数据/写数据时，需要设置为true
            connection.setDoOutput(true);
            // 设置传入参数的格式:请求参数应该是 name1=value1&name2=value2 的形式。
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            // 通过连接对象获取一个输出流
            outputStream = connection.getOutputStream();
            // 通过输出流对象将参数写出去/传输出去,它是通过字节数组写出的
            outputStream.write(param.getBytes());
            // 通过连接对象获取一个输入流，向远程读取
            if (connection.getResponseCode() == 200) {
                inputStream = connection.getInputStream();
                // 对输入流对象进行包装:charset根据工作项目组的要求来设置
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
                StringBuilder sbf = new StringBuilder();
                String temp;
                // 循环遍历一行一行读取数据
                while ((temp = bufferedReader.readLine()) != null) {
                    sbf.append(temp);
                    sbf.append(System.getProperty("line.separator"));
                }
                result = sbf.toString();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (null != bufferedReader) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != outputStream) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
        return result;
    }

    /**
     * 将map型转为请求参数型
     *
     * @param data
     * @return
     */
    public static String urlencode(Map<String, ?> data) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, ?> i : data.entrySet()) {
            try {
                sb.append(i.getKey()).append("=").append(URLEncoder.encode(i.getValue() + "", "UTF-8")).append("&");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        String result = sb.toString();
        result = result.substring(0, result.lastIndexOf("&"));
        return result;
    }

}
